package santeclair.connexion.util.journalisation;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;

import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.XmlMappingException;
import org.springframework.stereotype.Component;

import santeclair.connexion.bean.journalisation.FormatEchangeEnum;
import santeclair.connexion.bean.journalisation.TypeEchangeJournalisationEnum;
import santeclair.connexion.bean.journalisation.TypeJournalisationEnum;
import santeclair.connexion.bean.trame.DonneesTrame;
import santeclair.connexion.bean.trame.aller.calcul.DemandeCalculRemboursement;
import santeclair.connexion.bean.trame.aller.identification.DemandeIdentification;
import santeclair.connexion.domaine.parametrage.Journalisation;
import santeclair.connexion.domaine.parametrage.StructureTrame;
import santeclair.connexion.service.journalisation.JournalisationService;
import santeclair.lunar.framework.util.CompressionUtils;
import santeclair.referentiel.service.OrganismeService;

@Component
public class JournalisationHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(JournalisationHelper.class);

    @Autowired
    private Marshaller marshaller;

    @Autowired
    private JournalisationService journalisationService;

    @Autowired
    private OrganismeService organismeService;

    public void journaliserTrame(Journalisation journalisationTrame, boolean journaliser) {
        if (journalisationTrame != null && journalisationTrame.getFormatEchange() != null && journaliser) {
            Object trame = journalisationTrame.getDonneesTrame();
            if (trame != null) {
                FormatEchangeEnum key = journalisationTrame.getFormatEchange();
                switch (key) {

                case XML:
                    if (trame instanceof String) {
                        journalisationTrame.setTrame(CompressionUtils.compress(journalisationTrame.getDonneesTrame().toString()));
                        journalisationService.journaliser(journalisationTrame);
                    } else {
                        StringWriter writer = marshalTrameXml(trame);
                        journalisationTrame.setTrame(CompressionUtils.compress(writer.toString()));
                        journalisationService.journaliser(journalisationTrame);
                    }
                    break;

                default:
                    journalisationTrame.setTrame(CompressionUtils.compress(journalisationTrame.getDonneesTrame().toString()));
                    journalisationService.journaliser(journalisationTrame);
                    break;
                }
            }
        }
    }

    private StringWriter marshalTrameXml(Object trame) {
        StringWriter writer = new StringWriter();
        Result result = new StreamResult(writer);
        try {
            marshaller.marshal(trame, result);
        } catch (XmlMappingException e) {
            e.printStackTrace();
            LOGGER.error("Erreur pendant la journalisation de la trame lors de l'identification", e);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error("Erreur pendant la journalisation de la trame lors de l'identification", e);
        }
        return writer;
    }

    public Journalisation getJournalisationIdentAller(DemandeIdentification demandeIdentification, StructureTrame structureTrameIdentAller,
                    FormatEchangeEnum formatEchangeEnum, String codeOrganisme, Object trame, String service) {
        return getJournalisation(demandeIdentification, structureTrameIdentAller, formatEchangeEnum, codeOrganisme, trame, service, TypeJournalisationEnum.requete);
    }

    public Journalisation getJournalisationIdentRetour(DemandeIdentification demandeIdentification,
                    FormatEchangeEnum formatEchangeEnum, String codeOrganisme, String service) {
        return getJournalisation(demandeIdentification, null, formatEchangeEnum, codeOrganisme, null, service, TypeJournalisationEnum.reponse);
    }

    public Journalisation getJournalisationForDemandeCalcul(DemandeCalculRemboursement demandeCalculRemboursement, StructureTrame structureTrame,
                    FormatEchangeEnum formatEchange,
                    String codeOrganisme, Object trame, String service) {
        return getJournalisation(demandeCalculRemboursement, structureTrame, formatEchange, codeOrganisme, trame, service, TypeJournalisationEnum.requete);
    }

    public Journalisation getJournalisationForRetourCalcul(DemandeCalculRemboursement demandeCalculRemboursement, StructureTrame structureTrame,
                    FormatEchangeEnum formatEchange,
                    String codeOrganisme, String service) {
        return getJournalisation(demandeCalculRemboursement, structureTrame, formatEchange, codeOrganisme, null, service, TypeJournalisationEnum.reponse);
    }

    public Journalisation getJournalisationGPS(String application, String identifiantMetier, String trame, String codeOrganisme, TypeJournalisationEnum typeJournalisation) {
        Journalisation journalisation = new Journalisation();
        journalisation.setApplication(application);
        journalisation.setIdentifiantMetier(identifiantMetier);
        journalisation.setDonneesTrame(trame);
        journalisation.setType(typeJournalisation);
        journalisation.setTypeEchangeJournalisationEnum(TypeEchangeJournalisationEnum.BACKOFFICE_ASSUREUR);
        journalisation.setCodeOrganisme(codeOrganisme);
        if (codeOrganisme != null) {
            journalisation.setIdentifiantOrganisme(organismeService.getByCode(codeOrganisme).getId());
        }
        journalisation.setFormatEchange(FormatEchangeEnum.XML);
        journalisation.setDate(new Date());
        return journalisation;
    }

    private Journalisation getJournalisation(DonneesTrame donneesTrame, StructureTrame structureTrameIdentAller,
                    FormatEchangeEnum formatEchangeEnum, String codeOrganisme, Object trame, String service, TypeJournalisationEnum typeJournalisation) {
        Journalisation journalisation = new Journalisation();
        journalisation.setApplication(donneesTrame.getApplication());
        journalisation.setIdentifiantMetier(donneesTrame.getIdentifiantMetier());
        journalisation.setType(typeJournalisation);
        journalisation.setTypeEchangeJournalisationEnum(TypeEchangeJournalisationEnum.BACKOFFICE_ASSUREUR);
        journalisation.setFormatEchange(formatEchangeEnum);
        if (structureTrameIdentAller != null) {
            journalisation.setCodeStructureTrame(structureTrameIdentAller.getCode());
        }
        journalisation.setDonneesTrame(trame);
        journalisation.setCodeOrganisme(codeOrganisme);
        if (codeOrganisme != null) {
            journalisation.setIdentifiantOrganisme(organismeService.getByCode(codeOrganisme).getId());
        }
        journalisation.setService(service);
        journalisation.setDate(new Date());
        return journalisation;
    }

    public void updatCodeStructureTrameJournalisation(Journalisation journalisation, StructureTrame structureTrame) {
        if (structureTrame != null && journalisation != null) {
            journalisation.setCodeStructureTrame(structureTrame.getCode());
        }
    }

}
